package com.googlecode.cswish.struts.conversion;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.googlecode.cswish.model.ModelInfo;
import com.googlecode.cswish.model.PropertyInfo;
import com.googlecode.cswish.struts.hibernate.DynamicClassLoaderFactory;
import com.googlecode.cswish.struts.spring.BeanIntrospector;
import com.googlecode.cswish.struts.spring.ObjectFactory;
import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.reflection.ReflectionProvider;

/**
 * Call BeanIntrospector to get the correct List type
 * 
 * @author feng Date: 2009-4-3
 */
public class DefaultObjectTypeDeterminer extends
		com.opensymphony.xwork2.conversion.impl.DefaultObjectTypeDeterminer {
	protected final Log logger = LogFactory.getLog(getClass());
	
	private BeanIntrospector beanIntrospector;
	
	private DynamicClassLoaderFactory dynamicClassLoaderFactory;

	@Inject
	public DefaultObjectTypeDeterminer(@Inject XWorkConverter conv,
			@Inject ReflectionProvider prov) {
		super(conv, prov);
		
		beanIntrospector = ObjectFactory.getInstance().getBean(BeanIntrospector.class, false);
		dynamicClassLoaderFactory = ObjectFactory.getInstance().getBean(DynamicClassLoaderFactory.class, false);
	}
	
	@Override
	public Class getElementClass(Class parentClass, String property, Object key) {
		Class clazz = null;
		String className = parentClass.getName();
		ModelInfo modelInfo = beanIntrospector.getModelInfo(className);
		if (modelInfo != null) {
			PropertyInfo propertyInfo = modelInfo.getProperty(property);
			String type = propertyInfo.getGenericType();
			ModelInfo info = beanIntrospector.getModelInfo(type);
			if (ModelInfo.isDynamicClass(info.getType())) {
				ClassLoader classLoader = dynamicClassLoaderFactory.getClassLoader(info.getType(), true);
				Thread.currentThread().setContextClassLoader(classLoader);
				try {
					clazz = Class.forName(info.getType(), true, classLoader);
				} catch (ClassNotFoundException e) {
					logger.error("Can't find class:" + info.getType(), e);
				}
			} else {
				clazz = propertyInfo.getGenericTypeClass();
			}
		}
		return clazz != null ? clazz : super.getElementClass(parentClass, property, key);
	}
}
